package com.fastwire.carriere.rad.snmpadapter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.snmp4j.smi.Integer32;

import com.fastwire.carriere.common.constant.AppConstants;
import com.fastwire.carriere.common.util.CommonLogger;
import com.fastwire.carriere.rad.entity.Rad;
import com.fastwire.carriere.rad.entity.RadAlarm;
import com.fastwire.carriere.rad.entity.RadLog;
import com.fastwire.carriere.rad.entity.RadTermPoint;
import com.fastwire.carriere.rad.util.NetworkUtil;

/*
 * Creted on 20120225 Author: Lei Jun
 */
public class SnmpAdapter
{
    private SnmpAdmin snmpadmin = new SnmpAdmin();
    
    public boolean getRadInfo(Rad rad)
    {
        if (null == rad)
        {
            CommonLogger.info(this, "rad is null");
            return false;
        }
        String ip = rad.getIpAddr();
        if (null == ip)
        {
            CommonLogger.info(this, "rad ip should no be null");
            return false;
        }

        try
        {
            if (!snmpadmin.start(ip + "/161", SnmpRadConstants.COMMUNITY_Read))
            {
                CommonLogger.error(this, "error start: " + ip);
                return false;
            }

            rad.setDefaultGWValidate(
                    snmpadmin.snmpGet(SnmpRadConstants.OID_systemDefaultGateway),
                    snmpadmin.snmpGet(SnmpRadConstants.OID_atmNteHostIP),
                    snmpadmin.snmpGet(SnmpRadConstants.OID_atmNteHostMask));

            rad.setSysName(snmpadmin.snmpGet(SnmpRadConstants.OID_sysName));
            rad.setSysDescr(snmpadmin.snmpGet(SnmpRadConstants.OID_sysDescr));
            rad.setSysObjectID(snmpadmin.snmpGet(SnmpRadConstants.OID_sysObjectID));
            rad.setSysUpTime(snmpadmin.snmpGet(SnmpRadConstants.OID_sysUpTime));
            rad.setSysContact(snmpadmin.snmpGet(SnmpRadConstants.OID_sysContact));
            rad.setSysLocation(snmpadmin.snmpGet(SnmpRadConstants.OID_sysLocation));
            rad.setSysServices(snmpadmin.snmpGet(SnmpRadConstants.OID_sysServices));
            
            rad.setNeID("ARRTR.AR1-ARRTR-H8-011");   // should from sysName and Desr
            
            setRadInterface(snmpadmin, rad);
            
            rad.setDiscoveryDate(new Date());
            rad.setStatus(AppConstants.NE_STATUS_ACTIVE);

            snmpadmin.stop();
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    // get all the logs from a rad and then clear the log buffer
    public List<RadLog> getRadLogs(String ip)
    {
        if (!NetworkUtil.ipv4Check(ip))
        {
            CommonLogger.info(this, "rad ip is not correct"+ip);
            return null;
        }

        //SnmpAdmin snmpadmin = new SnmpAdmin();
        List<RadLog> logs = new ArrayList<RadLog>();
        try
        {
            if (!snmpadmin.start(ip + "/161", SnmpRadConstants.COMMUNITY_Read))
            {
                CommonLogger.error(this, "error start: " + ip);
                return null;
            }

            List<String> msges = snmpadmin.getTableAsStrings(SnmpRadConstants.OID_atmGenSysLogMessage);
            //List<String> msges = snmpadmin.snmpWalk(SnmpRadConstants.OID_atmGenSysLogEntry);
            
            // then clear the logs, else next time it will get the same logs
            // ?? 
            snmpadmin.snmpSet(SnmpRadConstants.OID_atmGenSysLogClearAll, new Integer32(3));
            
            long index = 0;
            for(String msg : msges)
            {
                RadLog log = new RadLog(ip);
                log.setIndex(++index);
                log.setMessage(msg);
                log.setUpdateTime(new Date());
                
                logs.add(log);
            }
            
            snmpadmin.stop();
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return null;
        }
        
        return logs;
    }
    
    //--------------------------------------------------------;
    //get alarms from rad
    public List<RadAlarm> getRadAlarms(String ip)
    {
        if (!NetworkUtil.ipv4Check(ip))
        {
            CommonLogger.info(this, "rad ip is not correct"+ip);
            return null;
        }        

        //SnmpAdmin snmpadmin = new SnmpAdmin();
        List<RadAlarm> alarms = new ArrayList<RadAlarm>();
        try
        {
            if (!snmpadmin.start(ip + "/161", SnmpRadConstants.COMMUNITY_Read))
            {
                CommonLogger.error(this, "error start: " + ip);
                return null;
            }

            List<String> msges = snmpadmin.getTableAsStrings(SnmpRadConstants.OID_atmGenSysLogMessage);
            //snmpadmin.snmpSet(SnmpRadConstants.OID_atmGenSysLogClearAll, new Integer32(3));
            //long index = 0;
            for(String msg : msges)
            {
                RadAlarm alm = new RadAlarm(ip);
                
                alarms.add(alm);
            }
            
            snmpadmin.stop();
        }
        catch (IOException e)
        {
            e.printStackTrace();
            return null;
        }

        return alarms;
    }
    
    // 192.168.10.0/24    
    public List<Rad> getAllRadInfo(List<String> ipList)
    {
        List<Rad> radList = new ArrayList<Rad>();
        for (String ip : ipList)
        {
            CommonLogger.info(this, "Processing rad info: " + ip);

            // InetAddress ad = InetAddress.getByName(ip); //
            // "192.168.1.119 ");
            if (NetworkUtil.isReachable(ip, 3000)) // 5000
            {
                // System.out.println("OK." + ad.getHostAddress());
                Rad rad = new Rad(ip);
                if (getRadInfo(rad))
                {
                    radList.add(rad);
                }
            }
            else
            {
                CommonLogger.info(this, ip + " is unreachable.");
            }
        }

        return radList;
    }

    /*
     * (non-Javadoc)
     */    
    public String loopback(String ip, int portType, String testType)
    {
        String rlt = null;
        try
        {
            //SnmpAdmin snmpadmin = new SnmpAdmin();
            if (!snmpadmin.start(ip + "/161", SnmpRadConstants.COMMUNITY_Write))
            {
                return "failed to start.";
            }
            
            int iTest = 0;
            //HS Loopback
            if(SnmpRadConstants.HS_TPTYPE == portType)
            {
                if(0 == testType.compareToIgnoreCase(SnmpRadConstants.LB_EXTERNAL))
                {
                    iTest = 4;
                }
                else if(0 == testType.compareToIgnoreCase(SnmpRadConstants.LB_INTERNAL))
                {
                    iTest = 2;
                }
                rlt = snmpadmin.snmpSet(SnmpRadConstants.OID_prtGenTestCmd, new Integer32(iTest));
            }
            else if(SnmpRadConstants.E1_TPTYPE == portType)  // E1 Loopback
            {
                if(0 == testType.compareToIgnoreCase(SnmpRadConstants.LB_EXTERNAL))
                {
                    iTest = 3;
                }
                else if(0 == testType.compareToIgnoreCase(SnmpRadConstants.LB_INTERNAL))
                {
                    iTest = 5;
                }
                rlt = snmpadmin.snmpSet(SnmpRadConstants.OID_dsx1LoopbackConfig, new Integer32(iTest));
            }
            else
            {
                CommonLogger.info(this, "no loopback test done");
            }
            
            // then check the test results????
            // rlt = 
            
            snmpadmin.stop();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }

        return rlt;
    }
    
    // parse the interface
    private void setRadInterface(SnmpAdmin snmpadmin, Rad rad)
    {
        List<List<String>> intfs = snmpadmin.getTableAsList(SnmpRadConstants.OID_ifEntry);
        
        Set<RadTermPoint> tps = new HashSet<RadTermPoint>();

        for(List<String> intf: intfs)
        {
            System.out.println(intf);

            String oid = intf.get(0);
            int i  = oid.lastIndexOf(".");  // "strOid.index" 
            int iV = Integer.valueOf(oid.substring(i+1));  // index
            String strOid = oid.substring(0,i);
            
            //"1.3.6.1.2.1.2.2.1.1"
            if(0 == strOid.compareTo(SnmpRadConstants.OID_ifIndex.toString()))  // idx
            {
                RadTermPoint tp = new RadTermPoint();
                tp.setPort(Integer.valueOf(intf.get(1)));
                tp.setStatus(AppConstants.NE_STATUS_ACTIVE);
                
                tps.add(tp);
            }
            //"1.3.6.1.2.1.2.2.1.2"
            else if(0 == strOid.compareTo(SnmpRadConstants.OID_ifDescr.toString()))  // dsecr
            {                
                for(RadTermPoint tp : tps)
                {
                    if(tp.getPort() == iV)
                    {
                        tp.setDescr(intf.get(1));
                        break;
                    }
                }
            }
            //"1.3.6.1.2.1.2.2.1.3"
            else if(0 == strOid.compareTo(SnmpRadConstants.OID_ifType.toString()))  // ifType
            {
                for(RadTermPoint tp : tps)
                {
                    if(tp.getPort() == iV)
                    {
                        tp.setType(Integer.valueOf(intf.get(1)));
                        break;
                    }
                }
            }
            //"1.3.6.1.2.1.2.2.1.4"
            else if(0 == strOid.compareTo(SnmpRadConstants.OID_ifMtu.toString()))  // ifMtu
            {
                for(RadTermPoint tp : tps)
                {
                    if(tp.getPort() == iV)
                    {
                        tp.setMtu(Integer.valueOf(intf.get(1)));
                        break;
                    }
                }
            }
            //"1.3.6.1.2.1.2.2.1.5"
            else if(0 == strOid.compareTo(SnmpRadConstants.OID_ifSpeed.toString()))  // ifSpeed
            {
                for(RadTermPoint tp : tps)
                {
                    if(tp.getPort() == iV)
                    {
                        tp.setSpeed(Integer.valueOf(intf.get(1)));
                        break;
                    }
                }
            }
            //"1.3.6.1.2.1.2.2.1.6"
            else if(0 == strOid.compareTo(SnmpRadConstants.OID_ifPhysAddress.toString()))  // ifPhysAddress
            {
                for(RadTermPoint tp : tps)
                {
                    if(tp.getPort() == iV)
                    {
                        tp.setPhysAddress(intf.get(1));
                        break;
                    }
                }
            }
            //"1.3.6.1.2.1.2.2.1.7"
            else if(0 == strOid.compareTo(SnmpRadConstants.OID_ifAdminStatus.toString()))  // ifAdminStatus
            {
                for(RadTermPoint tp : tps)
                {
                    if(tp.getPort() == iV)
                    {
                        int iTmp = Integer.valueOf(intf.get(1));
                        if(1 == iTmp)
                        {
                            tp.setAdminStatus("up");
                        }
                        else if(2 == iTmp)
                        {
                            tp.setAdminStatus("down");
                        }
                        else
                        {
                            tp.setAdminStatus("");
                        }
                        break;
                    }
                }
            }
            //"1.3.6.1.2.1.2.2.1.8"
            else if(0 == strOid.compareTo(SnmpRadConstants.OID_ifOperStatus.toString()))  // ifOperStatus
            {
                for(RadTermPoint tp : tps)
                {
                    if(tp.getPort() == iV)
                    {
                        int iTmp = Integer.valueOf(intf.get(1));
                        if(1 == iTmp)
                        {
                            tp.setOperStatus("up");
                        }
                        else if(2 == iTmp)
                        {
                            tp.setOperStatus("down");
                        }
                        else
                        {
                            tp.setOperStatus("");
                        }
                        break;
                    }
                }
            }
        }
        
        rad.setTermPoints(tps);
    }
}





